package org.jeecg.modules.common.utils;



import org.apache.commons.beanutils.PropertyUtils;
import org.jeecg.modules.common.baseentity.Row2ColGroupBy;
import org.jeecg.modules.common.baseentity.Row2ColModelPro;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

enum AggregateFunction {
    SUM,
    AVG;
}



public class DynamicPivot {
//    如果需要按照学生姓名和学科对成绩进行动态行列转换，可以这样调用：
//    Object[][] resultArray = dynamicPivot(studentList, "name", "subject");
//    如果需要按照学科和成绩对学生姓名进行动态行列转换，可以这样调用：
//    Object[][] resultArray = dynamicPivot(studentList, "subject", "score", "name");
    //动态行转列，转换属性可动态配置
//    public static <T> Object[][] dynamicPivot(List<T> list, Row2ColModelPro row2ColModelPro) {
//         //组装分组key的Function
//        Function<T, String> groupingKeyFunction = t -> {
//            StringBuilder keyBuilder = new StringBuilder();
//            for (String property : row2ColModelPro.getGroupFields()) {
//                try {
//                    Object propertyValue = PropertyUtils.getProperty(t, property);
//                    keyBuilder.append(propertyValue.toString()).append("-");
//                } catch (Exception e) {
//                    throw new RuntimeException(String.format("获取 %s 属性值失败", property));
//                }
//            }
//            return keyBuilder.toString();
//        };
//        // 根据配置的属性进行分组，并获取对应的值列表
//        Map<String, List<Object>> propertyValueListMap = list.stream()
//                .collect(Collectors.groupingBy(groupingKeyFunction, Collectors.mapping(t -> {
//                    try {
//                        List<Object> valueList = new ArrayList<>();
//                        for (String property : row2ColModelPro.getGroupFields()) {
//                            Object propertyValue = PropertyUtils.getProperty(t, property);
//                            valueList.add(propertyValue);
//                        }
//                        return valueList;
//                    } catch (Exception e) {
//                        throw new RuntimeException(String.format("获取 %s 属性值失败", Arrays.toString(row2ColModelPro.getGroupFields())));
//                    }
//                }, Collectors.toList())));
//        // 获取分组后的第一列的值，以此作为二维数组的行名
//        List<Object> rowNameList = new ArrayList<>(propertyValueListMap.keySet());
//        Collections.sort(rowNameList);
//
//        // 获取分组后需要展示的列名及顺序
//        Set<String> allPropertyValueSet = new HashSet<>();
//        for (List<Object> propertyValueList : propertyValueListMap.values()) {
//            allPropertyValueSet.addAll(propertyValueList);
//        }
//        List<String> columnList = new ArrayList<>(allPropertyValueSet);
//        Collections.sort(columnList);
//        // 构造动态行列转换后的二维数组
//        Object[][] resultArray = new Object[rowNameList.size() + 1][columnList.size() + 1];
//        // 第一行是展示列名
//        resultArray[0][0] = "名称";
//        for (int i = 0; i < columnList.size(); i++) {
//            resultArray[0][i + 1] = columnList.get(i);
//        }
//        // 将分组后的第一列的值填入第一列
//        for (int i = 0; i < rowNameList.size(); i++) {
//            resultArray[i + 1][0] = rowNameList.get(i);
//        }
//        // 将分组后需要展示的列填入对应位置
//        for (int i = 0; i < rowNameList.size(); i++) {
//            String groupName = (String) rowNameList.get(i);
//            List<Object> propertyValueList = propertyValueListMap.get(groupName).get(0);
//            for (int j = 0; j < propertyValueList.size(); j++) {
//                String columnValue = propertyValueList.get(j).toString();
//                int columnIndex = columnList.indexOf(columnValue);
//                resultArray[i + 1][columnIndex + 1] = "Y";
//            }
//        }
//        return resultArray;
//    }
    public static <T> Map<List<Row2ColGroupBy>, List<Object>> DynamicGroupingAndCalculation2(List<T> dataList, Row2ColModelPro row2ColModelPro){
        // 动态配置分组字段
        Map<List<Row2ColGroupBy>, List<Object>> groupedData = dataList.stream()
                .collect(Collectors.groupingBy(obj -> row2ColModelPro.getGroupByList().stream()
                        .map(groupBy -> new Row2ColGroupBy(groupBy.getFieldName(), BeanObjUtil.getFieldValueByName(obj, groupBy.getFieldName()) /*getFieldValueByFieldName(obj, groupBy.getFieldName())*/   ))
                        .collect(Collectors.toList())));
        //最后，你可以使用Stream的map和reduce方法对分组后的数据进行聚合统计计算。

//        groupedData.entrySet().stream()
//                .map(entry -> {
//                    // 根据需求对分组后的数据进行聚合统计计算
//                    // 返回聚合后的结果
//                })
//                .collect(Collectors.toList());

        return groupedData;
    }
    public static <T> Map<Object, Map<Object, Object>> DynamicGroupingAndCalculation(List<T> dataList, Row2ColModelPro row2ColModelPro) {

        // 动态行转列
        Map<Object, Map<Object, Object>> result = dataList.stream()
                .collect(Collectors.groupingBy(
                        rowItem -> {
                            String groupItem="";
                            for (String groupField:row2ColModelPro.getGroupFields()
                                 ) {
                                groupItem+=BeanObjUtil.getFieldValueByName(rowItem,groupField);

                            }
                            return groupItem;
                            },
                        Collectors.toMap(
                                rowItem ->{ /*key:返回动态列名*/ return BeanObjUtil.getFieldValueByName(rowItem,row2ColModelPro.getRow2colsKeyFields()[0]);}
                                ,vlueItem ->{ /*value：返回动态属性值*/
                                    Map<String,Object> valueMap = new HashMap<String,Object>();
                                    for (String valueField:row2ColModelPro.getNewColsValueByFields()
                                         ) {
                                        valueMap.put(valueField,BeanObjUtil.getFieldValueByName(vlueItem,valueField));
                                    }
                                    return valueMap;
                                    }
                               )
                ));

                //
        return result;

//            // 需要转换的属性
//            List<String> columnsToBeConverted = Arrays.asList("age", "salary");
//
//            // 分组及计算方式配置
//            Map<String, AggregateFunction> groupConfig = new HashMap<>();
//            groupConfig.put("age", AggregateFunction.AVG);
//            groupConfig.put("salary", AggregateFunction.SUM);
//
//            // 转换后的结果
//            Map<String, Map<String, Object>> resultMap = new HashMap<>();
//            for (String column : columnsToBeConverted) {
//                Map<String, Object> groupResultMap = new HashMap<>();
//                for (Map.Entry<String, AggregateFunction> entry : groupConfig.entrySet()) {
//                    String groupBy = entry.getKey();
//                    AggregateFunction func = entry.getValue();
//
//                    Map<String, List<Entity>> groupMap = dataList.stream()
//                            .collect(Collectors.groupingBy(e -> e.getValue(groupBy)));
//                    Map<String, Object> result = new HashMap<>();
//                    for (Map.Entry<String, List<Entity>> groupEntry : groupMap.entrySet()) {
//                        String key = groupEntry.getKey();
//                        List<Integer> values = groupEntry.getValue().stream()
//                                .map(e -> e.getValue(column))
//                                .collect(Collectors.toList());
//                        Object groupValue;
//                        switch (func) {
//                            case SUM:
//                                groupValue = values.stream().mapToInt(Integer::intValue).sum();
//                                break;
//                            case AVG:
//                                groupValue = values.stream().mapToInt(Integer::intValue).average().orElse(0);
//                                break;
//                            // 可扩展其他计算方式，如最大值、最小值等
//                            default:
//                                groupValue = null;
//                                break;
//                        }
//                        result.put(key, groupValue);
//                    }
//                    groupResultMap.put(groupBy, result);
//                }
//                resultMap.put(column, groupResultMap);
//            }
//
//            System.out.println(resultMap);
//            // 输出结果：{age={female={avg=29.0}, male={avg=27.333333333333332}}, salary={female={sum=4300}, male={sum=7000}}}
        }

//    /**
//     * 将数据分组，根据方法引用（bean的get方法）
//     *
//     * @param list      为分组的数据
//     * @param
//     */
//    @SafeVarargs
//    public static <T, R> Map<String, List<T>> groupingBy(List<T> list, String... fieldNames) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//       // Class clazz = list.get(0).getClass();
//        Class<?> clazz = Class.forName(list.get(0).getClass().toString());
//        Function<T, R>[] funs = new Function<T, R>[];
//        for (int i = 0; i < fieldNames.length; i++) {
//            char[] methodName=fieldNames[i].toCharArray();
//            methodName[0]-=32;//首字母转为大写
//            String getMethodName = "get"+String.valueOf(methodName);
//
//            funs[i] = (Function<T, R>) clazz.getMethod(getMethodName).invoke(null);
//
//            //BeanObjUtil.getGetMethodByFieldName(T::getClass,fieldNames[i]);
//            //funs[i] = BeanObjUtil.getGetMethodByFieldName(clazz,fieldNames[i]);
//        }
//
//        return list.stream().collect(Collectors.groupingBy(t -> groupingBy(t, funs)));
//    }
    /**
     * 将数据分组，根据方法引用（bean的get方法）
     *
     * @param list      为分组的数据
     * @param functions get方法数组   例如：Student::getName
     */
    @SafeVarargs
    public static <T, R> Map<String, List<T>> groupingBy(List<T> list, Function<T, R>... functions) {
        return list.stream().collect(Collectors.groupingBy(t -> groupingBy(t, functions)));
    }

    /**
     * 分组工具根据函数式接口使用分组，将数据根据分组结果进行拆分
     */
    @SafeVarargs
    public static <T, R> String groupingBy(T t, Function<T, R>... functions) {
        if (functions == null || functions.length == 0) {
            throw new NullPointerException("functions数组不可以为空");
        } else if (functions.length == 1) {
            return functions[0].apply(t).toString();
        } else {
            return Arrays.stream(functions).map(fun -> fun.apply(t).toString()).reduce((str1, str2) -> str1 + "|" + str2).get();
        }
    }
}
